<template>
  <div ref="chartRef" :style="{ width: width, height: height }" class="echarts-chart"></div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts'

interface Props {
  /** 图表配置 */
  option: any
  /** 图表宽度 */
  width?: string
  /** 图表高度 */
  height?: string
  /** 主题 */
  theme?: string
  /** 是否自动调整大小 */
  autoResize?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  width: '100%',
  height: '400px',
  theme: 'default',
  autoResize: true
})

const emit = defineEmits<{
  'chart-ready': [chart: echarts.ECharts]
  'chart-click': [params: any]
  'chart-dblclick': [params: any]
  'chart-mouseover': [params: any]
  'chart-mouseout': [params: any]
}>()

const chartRef = ref<HTMLDivElement>()
let chartInstance: echarts.ECharts | null = null
let resizeObserver: ResizeObserver | null = null

/** 初始化图表 */
const initChart = () => {
  if (!chartRef.value) return

  // 销毁已存在的图表实例
  if (chartInstance) {
    chartInstance.dispose()
  }

  // 创建新的图表实例
  chartInstance = echarts.init(chartRef.value, props.theme)

  // 设置图表配置
  if (props.option) {
    chartInstance.setOption(props.option, true)
  }

  // 绑定事件
  bindEvents()

  // 触发图表就绪事件
  emit('chart-ready', chartInstance)

  // 设置自动调整大小
  if (props.autoResize) {
    setupResize()
  }
}

/** 绑定图表事件 */
const bindEvents = () => {
  if (!chartInstance) return

  chartInstance.on('click', (params) => {
    emit('chart-click', params)
  })

  chartInstance.on('dblclick', (params) => {
    emit('chart-dblclick', params)
  })

  chartInstance.on('mouseover', (params) => {
    emit('chart-mouseover', params)
  })

  chartInstance.on('mouseout', (params) => {
    emit('chart-mouseout', params)
  })
}

/** 设置自动调整大小 */
const setupResize = () => {
  if (!chartRef.value || !chartInstance) return

  // 监听窗口大小变化
  window.addEventListener('resize', handleResize)

  // 使用 ResizeObserver 监听容器大小变化
  if (window.ResizeObserver) {
    resizeObserver = new ResizeObserver(handleResize)
    resizeObserver.observe(chartRef.value)
  }
}

/** 处理大小调整 */
const handleResize = () => {
  if (chartInstance) {
    chartInstance.resize()
  }
}

/** 更新图表配置 */
const updateChart = (option: any, notMerge = false) => {
  if (chartInstance) {
    chartInstance.setOption(option, notMerge)
  }
}

/** 显示加载动画 */
const showLoading = (text = '加载中...') => {
  if (chartInstance) {
    chartInstance.showLoading('default', {
      text,
      color: '#409eff',
      textColor: '#000',
      maskColor: 'rgba(255, 255, 255, 0.8)',
      zlevel: 0
    })
  }
}

/** 隐藏加载动画 */
const hideLoading = () => {
  if (chartInstance) {
    chartInstance.hideLoading()
  }
}

/** 获取图表实例 */
const getChart = () => {
  return chartInstance
}

/** 获取图表图片 */
const getDataURL = (opts?: any) => {
  if (chartInstance) {
    return chartInstance.getDataURL(opts)
  }
  return ''
}

/** 销毁图表 */
const dispose = () => {
  if (chartInstance) {
    chartInstance.dispose()
    chartInstance = null
  }

  if (resizeObserver) {
    resizeObserver.disconnect()
    resizeObserver = null
  }

  window.removeEventListener('resize', handleResize)
}

/** 监听配置变化 */
watch(
  () => props.option,
  (newOption) => {
    if (newOption && chartInstance) {
      updateChart(newOption, true)
    }
  },
  { deep: true }
)

/** 监听主题变化 */
watch(
  () => props.theme,
  () => {
    // 主题变化时重新初始化图表
    nextTick(() => {
      initChart()
    })
  }
)

/** 组件挂载后初始化图表 */
onMounted(() => {
  nextTick(() => {
    initChart()
  })
})

/** 组件卸载前销毁图表 */
onBeforeUnmount(() => {
  dispose()
})

/** 暴露方法 */
defineExpose({
  updateChart,
  showLoading,
  hideLoading,
  getChart,
  getDataURL,
  dispose
})
</script>

<style scoped>
.echarts-chart {
  min-height: 200px;
}
</style>
